/*Android、iOS等都是多线程的，遇到耗时任务开启子线程，而Node、Dart都是单线程的，结合时间循环实现异步
* 在Dart中代码在isolates中运行，并非传统意义的线程，只是使用相似
*   1. 每个isolates都有自己的内存且都是单线程，而传统线程是共享内存的
*   2. 避免了多线程共享数据的问题，也无需考虑死锁的问题
*   3. Dart的异步本质就是isolates运行模式，多个isolates并发
*
* 事件循环：所有事件(点击事件、网络请求事件、IO事件)放入事件队列中
*
* Dart中使用Future、async、await实现异步
*
* 多核cpu的利用：isolates(隔离)
* */

import 'dart:io';

import 'dart:isolate';

/// 需要延迟的运算（async）时，将其放入到延迟运算的队列（await）中去
///
/// 1.只有使用async的方法，才可以使用await调用方法
/// 2.如果一个方法中调用其他async方法是，必须在前面添加await关键字
/// 3.async是让方法变为异步，await是等待异步方法执行完成
/// 4.一个方法中使用await调用方法，该方法也必须是async的
void main() {
  // testNetwork();
  // futureChainCall();
  // doGetUser();
  // testDelayFuture();

  // 单独创建Isolate执行耗时方法，主线程不需要等待其执行完毕
  // createIsolates目标耗时函数，100给函数传递的参数
  Isolate.spawn(createIsolates, 100);
}

// Future+then
testNetwork() {
  print('main start...');
  var result = doGetUserInfo();
  // then获取正常结果
  result.then((value) => print('$value')).catchError((onError) {
    // catchError捕获异常
    print('$onError');
  }).whenComplete(() => {print('无论是否异常都会执行')});
  print('main end...');
}

// 模拟耗时网络请求,将耗时操作包裹到Future回调中
Future doGetUserInfo() {
  // 只要有返回结果，就会回调Future的then函数获取具体结果
  // 如果没有返回结果（有错误信息），需要在Future回调中抛出一个异常
  return Future(() {
    sleep(Duration(seconds: 3));
    throw Exception('出现异常');
    return "fauks--desc";
  });
}

// Future链式调用:三次网络调用，后面的调用需要使用前面的结果，解决回调嵌套问题
// 以下使用async+await可以更好的解决
futureChainCall() {
  // 简化使用回调的写法
  // Future.error
  /*Future.value(() {
    return "hello";
  }).then((value) => print('$value'));*/
  Future(() {
    print('第一次调用');
    return "first";
  }).then((value) {
    print('第二次调用');
    return 'second $value';
  }).then((value) {
    print('第三次调用');
    return 'third $value';
  }).catchError((error) {
    print('$error');
  });
}

// async+await 同步方式的异步调用
void doGetUser() async {
  var res1 = await getUser("fauks");
  print('getUser res1= $res1');
  var res2 = await getUser(res1);
  print('getUser res2= $res2');
  var res3 = await getUser(res2);
  print('getUser res3= $res3');
}

Future getUser(String argus) {
  // 直接返回目标对象，Dart自动包装为Future类型，语法糖
  // return "getUser" + argus;
  return Future(() {
    sleep(Duration(seconds: 1));
    return "getUser" + argus;
  });
}

// 测试延时异步 async+await:同步的方式写异步调用
testDelayFuture() {
  print("耗时方法开始于：" + DateTime.now().toString());
  // 异步开始
  doComplexJob();
  print('主线程执行结束');
}

// 异步方法 使用async声明异步，返回值为Future<T>，普通方法直接返回T
// async(async*与yield结合是个生成器，返回多个结果)，返回结果必须是Future
doComplexJob() async {
  Future<String> future = Future.delayed(
      Duration(seconds: 2), () => "耗时方法结束于：" + DateTime.now().toString());
  print(await future);
}

// 模拟复杂运算
createIsolates(int count) {
  int total = 0;
  for (int i = 0; i < count; i++) {
    total += i;
  }
  print(total);
}
